package org.goldfish.demo.multifrontend.messageboard.mobile.background

//import com.launchdarkly.eventsource.EventSources
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Intent
import android.os.IBinder
import androidx.core.app.NotificationCompat
import com.google.gson.Gson
import com.launchdarkly.eventsource.ConnectStrategy
import com.launchdarkly.eventsource.EventSource
import com.launchdarkly.eventsource.MessageEvent
import com.launchdarkly.eventsource.background.BackgroundEventHandler
import com.launchdarkly.eventsource.background.BackgroundEventSource
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import org.goldfish.demo.multifrontend.messageboard.mobile.R
import org.goldfish.demo.multifrontend.messageboard.mobile.model.LoginReq
import org.goldfish.demo.multifrontend.messageboard.mobile.model.MessageView
import org.goldfish.demo.multifrontend.messageboard.mobile.network.ApiClient
import org.goldfish.demo.multifrontend.messageboard.mobile.network.Logger
import java.net.URI
import java.util.Objects
import java.util.concurrent.TimeUnit

class MessageSseService : Service() {

    companion object {
        private const val CHANNEL_ID = "sse_channel"
        private const val NOTIF_ID = 1001
    }

    private val gson = Gson()
    private val job = SupervisorJob()
    private val scope = CoroutineScope(Dispatchers.IO + job)
    private var backgroundEventSource: BackgroundEventSource? = null

    override fun onCreate() {
        super.onCreate()
        createNotificationChannel()
        startForeground(
            NOTIF_ID,
            NotificationCompat.Builder(this, CHANNEL_ID).setContentTitle("消息监听中")
                .setContentText("正在接收实时消息…").setSmallIcon(R.mipmap.message_board_round)
                .build()
        )
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val baseUrl = ApiClient.loadIPInfo(application)
        when (ApiClient.hasAuth) {
            true -> {
                if (ApiClient.Token.isEmpty()){
                    Logger.e("请先登录", IllegalArgumentException("凭据加载失败"))
                    return START_NOT_STICKY
                }
            }
            else -> {
                Logger.e("请先登录", IllegalArgumentException("凭据加载失败"))
                return START_NOT_STICKY
            }
        }

        // 使用 runBlocking 阻塞获取 JWT
        scope.launch {
            val jwt = ApiClient.auth()
            startSse(baseUrl, jwt)
        }
        return START_STICKY
    }

    private fun startSse(baseUrl: String, jwtRaw: String) {
        // 1) 拼 URL，避免重复 /api 或多/少斜杠
        fun join(base: String, path: String): String {
            val b = if (base.endsWith("/")) base.dropLast(1) else base
            val p = if (path.startsWith("/")) path else "/$path"
            return b + p
        }

        val sseUrl = join(baseUrl, "/api/messages/stream")

        Logger.i("SSE URL: $sseUrl")
        // 2) JWT 头保证只加一次 Bearer
        fun bearer(token: String) = if (token.startsWith("Bearer ")) token else "Bearer $token"
        val jwt = bearer(jwtRaw)

        // 3) 正确的 ConnectStrategy：带 Accept/Authorization；SSE 读超时为 0
        val cs = ConnectStrategy.http(URI(sseUrl)).header("Authorization", jwt)
            .header("Accept", "text/event-stream").header("Cache-Control", "no-cache")
            .connectTimeout(15, TimeUnit.SECONDS).readTimeout(0, TimeUnit.SECONDS) // SSE 不要读超时

        // 旧的关闭，新的启动
        backgroundEventSource?.close()

        val handler = object : BackgroundEventHandler {
            override fun onOpen() {
                Logger.d("SSE 打开连接: $sseUrl")
            }

            override fun onClosed() {
                Logger.d("SSE 连接关闭")
            }

            override fun onMessage(event: String?, messageEvent: MessageEvent) {
                val data = messageEvent.data
                scope.launch(Dispatchers.Main) {
                    SseRepository.emit(data)
                    showNotification(data)
                }
            }

            override fun onComment(comment: String?) {}
            override fun onError(t: Throwable) {
                // 如果还是 400，优先去看服务器日志（Spring 会给出具体原因）
                Logger.e("SSE Error", t)
            }
        }

        backgroundEventSource = BackgroundEventSource.Builder(
            handler, EventSource.Builder(cs)                 // ✅ 新版 API：传 Builder(connectStrategy)
                .retryDelay(1, TimeUnit.SECONDS)    // 基础重试间隔
                .retryDelayResetThreshold(60, TimeUnit.SECONDS)
        ).threadBaseName("SSE").build()

        backgroundEventSource?.start()
    }


    private fun showNotification(data: String) {

        val dataModel: MessageView?
        try {
            dataModel = Objects.requireNonNull(gson.fromJson(data, MessageView::class.java))
        } catch (exception: Exception) {
            Logger.e("JSON 解析错误", exception)
            return
        }


        val notif = NotificationCompat.Builder(this, CHANNEL_ID)
//            .setSmallIcon(android.R.drawable.)
            .setSmallIcon(R.drawable.message_board_foreground)
            .setContentTitle("新消息 ${dataModel.sender}")
            .setContentText(dataModel.message.take(20) + "...")
            .setPriority(NotificationCompat.PRIORITY_HIGH).setAutoCancel(true).build()
        val mgr = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        mgr.notify(System.currentTimeMillis().toInt(), notif) // 用时间戳区分每条通知
    }

    override fun onDestroy() {
        backgroundEventSource?.close()
        backgroundEventSource = null
        scope.cancel() // 释放协程
        super.onDestroy()
    }

    override fun onBind(intent: Intent?): IBinder? = null

    private fun createNotificationChannel() {
        val channel = NotificationChannel(
            CHANNEL_ID, "SSE 消息", NotificationManager.IMPORTANCE_LOW
        )
        (getSystemService(NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel(
                channel
            )
    }
}
